package com.xyoto.community.service.impl;

import com.github.pagehelper.PageHelper;
import com.xyoto.community.cache.CacheInstruction;
import com.xyoto.community.cache.UserCache;
import com.xyoto.community.constant.*;
import com.xyoto.community.dto.*;
import com.xyoto.community.entity.main.AnonymousUser;
import com.xyoto.community.entity.main.FanFollow;
import com.xyoto.community.entity.main.Topic;
import com.xyoto.community.entity.main.User;
import com.xyoto.community.enums.CommonEnum;
import com.xyoto.community.enums.FileEnum;
import com.xyoto.community.enums.UserEnum;
import com.xyoto.community.enums.WechatLoginEnum;
import com.xyoto.community.exception.ExceptionUtils;
import com.xyoto.community.mapper.comment.DynamicCommentMapper;
import com.xyoto.community.mapper.love.*;
import com.xyoto.community.mapper.main.*;
import com.xyoto.community.mapper.picture.DynamicPictureMapper;
import com.xyoto.community.po.*;
import com.xyoto.community.pojo.ContentCheckResult;
import com.xyoto.community.pojo.DynamicStatistic;
import com.xyoto.community.service.*;
import com.xyoto.community.utils.*;
import com.xyoto.community.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;


/**
 * ClassName:   用户Service接口实现类
 * Author:      挽风
 * Date:        2020
 * Copyright:   2020 by 挽风1.0版本
 * Description:
 **/

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private FanFollowMapper fanFollowMapper;

    @Autowired
    private UserMapper userMapper;

    @Resource
    private XYOtoOss xyOtoOss;

    @Resource
    private HttpServletRequest httpServletRequest;

    @Autowired
    private TopicFollowMapper topicFollowMapper;

    @Autowired
    private ContentCheckUtils contentCheckUtils;

    @Autowired
    private DynamicLoveMapper dynamicLoveMapper;

    @Autowired
    private DynamicMapper dynamicMapper;

    @Autowired
    private DynamicCommentLoveMapper dynamicCommentLoveMapper;

    @Autowired
    private DynamicCommentReplyLoveMapper dynamicCommentReplyLoveMapper;

    @Autowired
    private QuestionCommentLoveMapper questionCommentLoveMapper;

    @Autowired
    private QuestionCommentReplyLoveMapper questionCommentReplyLoveMapper;

    @Autowired
    private DynamicCommentMapper dynamicCommentMapper;

    @Autowired
    private DynamicForwardMapper dynamicForwardMapper;

    @Autowired
    private DynamicPictureMapper dynamicPictureMapper;

    @Autowired
    private TopicMapper topicMapper;

    @Autowired
    private RedisCommonUtils redisCommonUtils;

    @Autowired
    private TopicService topicService;

    @Autowired
    private AnonyUserService anonyUserService;

    @Autowired
    private PictureService pictureService;

    @Autowired
    private MessageService messageService;

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private UserCacheService userCacheService;

    @Autowired
    private UserTitleService userTitleService;

    @Autowired
    private DynamicCacheService dynamicCacheService;

    @Autowired
    private TopicCacheService topicCacheService;

    @Autowired
    private PictureCacheService pictureCacheService;

    @Autowired
    private UserTitleCacheService userTitleCacheService;

    /**
     * 根据用户id查询用户头像、昵称
     *
     * @param userId 用户id
     * @return UserPO
     */
    @Override
    public UserPO getUserPartInfoById(Integer userId) {
        return userMapper.getUserPartInfoById(userId);
    }

    /**
     * 修改用户头像
     *
     * @param multipartFile
     * @return
     */
    @Override
    public Result updateMyAvatar(MultipartFile multipartFile) {
        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);

        // 检查头像文件
        checkAvatarSize(multipartFile);

        // 上传头像到Oss
        String avatarUrl = null;
        try {
            avatarUrl = xyOtoOss.uploadFileAvatar(multipartFile, OssBucketModuleName.USER);
        } catch (IOException e) {
            ExceptionUtils.error(FileEnum.FILE_UPLOAD_FAIL);
        }
        User user = userMapper.selectOneByUserId(userId);
        user.setAvatarUrl(avatarUrl);
        // 更新用户表
        Integer update = userMapper.updateBaseInfoByUser(user);
        if (update < DatabaseOperationResult.SUCCESS) {
            ExceptionUtils.error(FileEnum.AVATAR_SAVE_ERROR);
        }
        avatarUrl = PictureUtils.addPrefix(avatarUrl);
        // 更新redis中的用户信息
        UserCache userCache = userCacheService.getUserMessageFromUserCacheById(userId);
        userCache.setAvatarUrl(avatarUrl);
        userCacheService.updateUserCache(userCache);
        Map<String, String> data = new HashMap<>();
        data.put("url", avatarUrl);
        return Result.success(data);
    }

    /**
     * 修改用户昵称
     *
     * @param nickname 昵称
     * @return
     */
    @Override
    public Result updateMyNickname(String nickname) {
        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        if (nickname != null) {
            // 检查昵称是否合法
            checkNickname(nickname);
        }
        // 检查是否有重名
        Integer repeat = userMapper.countNickname(nickname);
        if (repeat > 0) {
            ExceptionUtils.error(UserEnum.USER_NICKNAME_REPEAT);
        }

        // 保存到数据库
        User user = userMapper.selectOneByUserId(userId);
        user.setNickname(nickname);
        Integer update = userMapper.updateBaseInfoByUser(user);
        // 检查是否更新到数据库成功
        checkUpdateSuccess(update);
        HashMap<String, String> data = new HashMap<>();
        data.put("nickname", user.getNickname());
        return Result.success(data);
    }

    /**
     * 修改用户性别
     *
     * @param gender 男、女
     * @return
     */
    public Result updateGender(String gender) {
        return updateGender(SexTransformUtil.transformSex(gender));
    }

    /**
     * 修改用户性别
     *
     * @param gender 性别：1男，2女
     * @return
     */
    @Override
    public Result updateGender(Short gender) {
        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        // 检查参数合法性
        checkGender(gender);

        // 保存到数据库
        User user = userMapper.selectOneByUserId(userId);
        if (user == null) {
            ExceptionUtils.error(UserEnum.USER_WX_MESSAGE_UPDATE_FAIL);
        }
        user.setGender(gender);
        Integer update = userMapper.updateBaseInfoByUser(user);
        // 判断是否保存到数据库成功
        checkUpdateSuccess(update);
        HashMap<String, String> data = new HashMap<>();
        data.put("gender", SexTransformUtil.transformSexStr(user.getGender()));
        return Result.success(data);
    }

    /**
     * 修改用户个性签名
     *
     * @param signature
     * @return
     */
    @Override
    public Result updateMySignature(String signature) {
        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        // 检查个性签名合理性
        if (signature != null) {
            checkSignature(signature);
        }
        // 更新到数据库
        User user = userMapper.selectOneByUserId(userId);
        user.setSignature(signature);
        Integer update = userMapper.updateBaseInfoByUser(user);
        // 判断是否保存成功
        checkUpdateSuccess(update);
        HashMap<String, String> data = new HashMap<>();
        data.put("signature", user.getSignature());
        return Result.success(data);
    }

    /**
     * 检查个性签名合理性
     *
     * @param signature
     */
    private void checkSignature(String signature) {
        // 判断个性签名是否过长
        if (signature == null || signature.length() > UserConstants.SIGNATURE_MAX_LENGTH) {
            ExceptionUtils.error(UserEnum.SIGNATURE_TOO_LONG);
        }
        if (!"".equals(signature)) {
            // 文本合法性检查
            pictureService.checkContent(new CheckContentDTO(signature));
        }
    }

    /**
     * 检查性别合理性
     *
     * @param gender 性别：1男，2女
     */
    private void checkGender(Short gender) {
        if (gender == null) {
            ExceptionUtils.error(CommonEnum.REQUEST_PARAM_ERROR);
        }
        // 参数值不是规定的值
        if (gender < UserConstants.GENDER_BOY || gender > UserConstants.GENDER_GIRL) {
            ExceptionUtils.error(UserEnum.GENDER_IS_ILLEGAL);
        }
    }

    /**
     * 检查是否更新到数据库成功
     *
     * @param rows
     */
    private void checkUpdateSuccess(Integer rows) {
        if (rows < DatabaseOperationResult.SUCCESS) {
            ExceptionUtils.error(UserEnum.USER_WX_MESSAGE_UPDATE_FAIL);
        }
    }


    /**
     * 检查检查用户名是否合理
     *
     * @param nickname
     */
    private void checkNickname(String nickname) {

        // 判断空字符串
        if (StringUtils.isEmpty(nickname)) {
            ExceptionUtils.error(UserEnum.USER_NICKNAME_CAN_NOT_BE_NULL);
        }

        //判断用户昵称的字数
        if (nickname.length() > UserConstants.USERNAME_LENGTH) {
            ExceptionUtils.error(UserEnum.USER_NAME_TOO_LONG);
        }
        // 文本合法性检查
        pictureService.checkContent(new CheckContentDTO(nickname));
    }

    /**
     * 检查头像文件大小等
     *
     * @param multipartFile
     */
    private void checkAvatarSize(MultipartFile multipartFile) {
        // 图片文件为空
        if (multipartFile == null) {
            ExceptionUtils.error(FileEnum.FILE_IS_NULL);
        }
        // 检查文件大小
        if (multipartFile.getSize() > FileConstants.MAX_SIZE) {
            ExceptionUtils.error(FileEnum.FILE_SIZE_OVERFLOW);
        }
        // 检测图片是否安全
        ContentCheckResult contentCheckResult = contentCheckUtils.checkImg(multipartFile);
        if (contentCheckResult != null) {
            // 图片违法
            ExceptionUtils.error(FileEnum.PICTURE_IS_ILLEGAL);
        }
    }

    /**
     * 分页获取我关注的用户信息列表
     *
     * @param pageDTO 分页Query封装
     * @return List
     */
    @Override
    public Result getMyFollowList(PageDTO pageDTO) {

        // 获取当前登录用户的id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);

        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());

        // 查询我关注的用户列表
        List<MyFollowUserInfoPO> list = userMapper.getMyFollowList(userId, pageDTO.getEndIndexId());

        if (list.size() != 0) {
            // 查询是否进行了互关
            for (MyFollowUserInfoPO info : list) {
                Short myStatus = info.getFollowStatus();
                Short followStatus = fanFollowMapper.getIsCorrelateById(info.getUserId(), userId);
                // 判断互关
                if (myStatus == FollowStatus.FOLLOW && myStatus.equals(followStatus)) {
                    info.setFollowStatus(FollowStatus.USER_CORRELATE);
                } else {
                    // 只是我关注了他
                    info.setFollowStatus(FollowStatus.ONLY_I_FOLLOW_HIM);
                }
                // 获取头衔
                UserTitlePO userTitlePo = userTitleCacheService.getUserTitleFromCache(info.getTitleNameId(), info.getTitleLogoId());
                info.setUserTitlePO(userTitlePo);
            }
        }
        return list.size() == 0 ? Result.success(new PageUtils<>())
                : Result.success(PageUtils.restPage(list));
    }

    /**
     * 根据用户id获取用户详情信息
     *
     * @param userId 需要查询的用户id
     * @return 用户详情信息
     */
    @Override
    public Result getUserDetailsById(Integer userId) {
        if (null == userId || userId <= 0) {
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }

        // 获取当前用户id
        Integer currentUserId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);

        // 查询用户信息
        UserPO userPO = userMapper.getUserPartInfoById(userId);
        if (userPO == null) {
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }
        // 查询用户活跃度排行
        // 排名 从redis中获取排名
        long rank = redisCommonUtils.zrevrank(CacheInstruction.USER_RANK, userId);
        if (rank == -1) {
            //取出最大长度，返回加一数据
            Long size = redisCommonUtils.getZsetSize(CacheInstruction.USER_RANK);
            rank = size + 1;
        } else {
            rank += 1;
        }
        // 获取两个用户的关注状态
        FanFollow iFollowHim = fanFollowMapper.getUserFollowStatus(currentUserId, userId);
        FanFollow himFollowMe = fanFollowMapper.getUserFollowStatus(userId, currentUserId);
        short followStatus;
        if (iFollowHim != null && himFollowMe != null
                && Short.valueOf(FollowStatus.FOLLOW).equals(himFollowMe.getFollowStatus())
                && Short.valueOf(FollowStatus.FOLLOW).equals(iFollowHim.getFollowStatus())) {
            // 互关
            followStatus = FollowStatus.USER_CORRELATE;
        } else if (himFollowMe != null && Short.valueOf(FollowStatus.FOLLOW).equals(himFollowMe.getFollowStatus())) {
            // 只是他关注我
            followStatus = FollowStatus.ONLY_HIM_FOLLOW_ME;
        } else if (iFollowHim != null && Short.valueOf(FollowStatus.FOLLOW).equals(iFollowHim.getFollowStatus())) {
            // 只是我关注他
            followStatus = FollowStatus.ONLY_I_FOLLOW_HIM;
        } else {
            // 双方均未关注
            followStatus = FollowStatus.UN_FOLLOW;
        }
        OtherPeopleUserVo otherPeopleUserVo = new OtherPeopleUserVo(userId, userPO.getAvatarUrl()
                , userPO.getNickname(), userPO.getSignature(), (int) rank, followStatus);

        // 获取头衔
        UserTitlePO userTitlePo = userTitleCacheService.getUserTitleFromCache(userPO.getTitleNameId(), userPO.getTitleLogoId());
        otherPeopleUserVo.setUserTitlePO(userTitlePo);
        return Result.success(otherPeopleUserVo);
    }

    /**
     * 获取我关注的话题
     *
     * @param pageDTO
     * @return
     */
    @Override
    public Result getMyFollowTopicList(PageDTO pageDTO) {
        // 获取当前用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
        // 查询用户关注的话题
        List<Integer> myFollowTopicIdList = topicFollowMapper.selectTopicIdListByUserIdAndFollowStatus(userId, FollowStatus.FOLLOW);
        // 调用话题服务接口
        List<TopicListVo> topicListVoList = topicService.listTopicBatchTopicIds(myFollowTopicIdList);
        PageUtils<TopicListVo> myFollowTopicVoPage = PageUtils.restPage(myFollowTopicIdList, topicListVoList);
        return Result.success(myFollowTopicVoPage);
    }

    /**
     * 修改用户出生日期
     *
     * @param birthStr 出生日期
     * @return
     */
    @Override
    public Result updateMyBirth(String birthStr) {
        // 获取当前用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        // 检查日期正确性
        Date birth = checkBirth(birthStr);
        // 计算出星座
        java.time.LocalDateTime localDateTime = birth.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        String constellation = StarUtils.calculateConstellation(localDateTime);
        // 保存到数据库
        User user = userMapper.selectOneByUserId(userId);
        if (user == null) {
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }
        user.setBirth(birth);
        Integer update = userMapper.updateBaseInfoByUser(user);
        if (update < DatabaseOperationResult.SUCCESS) {
            ExceptionUtils.error(UserEnum.USER_WX_MESSAGE_UPDATE_FAIL);
        }
        UpdateBirthVO updateBirthVO = new UpdateBirthVO(birthStr, constellation);
        return Result.success(updateBirthVO);
    }

    /**
     * 获取我的个人资料
     *
     * @return
     */
    @Override
    public Result getUserInfo() {
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        UserInfoPO user = userMapper.getUserInfo(userId);
        if (null == user) {
            ExceptionUtils.error(UserEnum.USER_NOT_EXIST);
        }
        UserInfoVO userInfoVO = new UserInfoVO();
        BeanUtils.copyProperties(user, userInfoVO);
        //判断是否存在生日
        if (user.getBirth() != null) {
            //日期转换获取生日和星座
            String birthday = new SimpleDateFormat("yyyy-MM-dd").format(user.getBirth());
            userInfoVO.setBirth(birthday);
            //获取星座
            LocalDateTime localDateTime = user.getBirth().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
            String star = StarUtils.calculateConstellation(localDateTime);
            userInfoVO.setStar(star);
        }
        //获取性别
        String sex = SexTransformUtil.transformSexStr(user.getGender());
        userInfoVO.setSex(sex);
        //todo学院库未判断
        userInfoVO.setCollage("");
        if (user.getAuthenticationStatus().equals(AuthenticationStatus.auth)) {
            userInfoVO.setAuthenticationStatus(AuthenticationStatus.NOT_AUTHENTICATION);
        }
        if (user.getAuthenticationStatus().equals(AuthenticationStatus.not_auth)) {
            userInfoVO.setAuthenticationStatus(AuthenticationStatus.AUTHENTICATION);
        }
        return Result.success(userInfoVO);
    }

    /**
     * 获取用户的头像，昵称，个性签名，获赞数，粉丝数，关注数，排名
     *
     * @return
     */
    @Override
    public Result getMy() {
        // 获取当前用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);

        // 获取用户的头像，昵称，个性签名，认证状态
        User user = userMapper.selectOneByUserId(userId);

        // 获赞数
        Integer beLovedCount = getBeLovedCountByUserId(userId);

        // 粉丝数
        Integer fansCount = fanFollowMapper.countFollowMeByUserIdAndStatus(userId, FollowStatus.FOLLOW);

        // 关注数
        Integer followCount = fanFollowMapper.countMyFollowByUserIdAndStatus(userId, FollowStatus.FOLLOW);

        // 排名 从redis中获取排名
        long rank = redisCommonUtils.zrevrank(CacheInstruction.USER_RANK, userId);
        if (rank == -1) {
            //取出最大长度，返回加一数据
            Long size = redisCommonUtils.getZsetSize(CacheInstruction.USER_RANK);
            rank = size + 1;
        } else {
            // 排名 = 索引+1
            rank++;
        }
        MyVo myVo = new MyVo();
        myVo.setAvatarUrl(user.getAvatarUrl());
        myVo.setNickname(user.getNickname());
        myVo.setUserId(userId);
        myVo.setSignature(user.getSignature());
        myVo.setAuthenticationStatus(user.getAuthenticationStatus());
        myVo.setBeLovedCount(beLovedCount);
        myVo.setFansCount(fansCount);
        myVo.setFollowCount(followCount);
        myVo.setRank((int) rank);

        // 获取头衔
        UserTitlePO userTitlePo = userTitleCacheService.getUserTitleFromCache(user.getTitleNameId(), user.getTitleLogoId());
        myVo.setUserTitlePO(userTitlePo);

        return Result.success(myVo);
    }

    @Override
    public Result getMyDynamicListByUserId(PageDTO pageDTO) {
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
        // 获取当前用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);

        //查询分页的动态数据
        List<MyDynamicListPO> dynamicListPOList = dynamicMapper.getMyDynamicList(pageDTO.getEndIndexId(), userId, null);
        //如果没有动态就直接返回
        if (dynamicListPOList.size() == 0) {
            return Result.success(PageUtils.restPage(new ArrayList<>()));
        }
        List<MyDynamicListVo> myDynamicListVoList = getDynamicList(dynamicListPOList, pageDTO, userId);
        return Result.success(PageUtils.restPage(dynamicListPOList, myDynamicListVoList));
    }

    @Override
    public Result getMyFansList(PageDTO pageDTO) {
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
        //获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);

        //获取用户的粉丝列表
        List<MyFollowUserInfoPO> myFollowUserInfoPOList = userMapper.getMyFansList(userId, pageDTO.getEndIndexId());
        if (myFollowUserInfoPOList.size() == 0) {
            return Result.success(new PageUtils<>());
        }
        HashMap<Integer, Integer> hashMap = new HashMap<>(32);
        //获取所有的粉丝id
        List<Integer> fansIds = myFollowUserInfoPOList.stream().map(MyFollowUserInfoPO::getUserId).collect(Collectors.toList());
        List<UserFollowStatusPO> userFollowStatusPo = userMapper.checkIsEachAttention(userId, fansIds);
        for (UserFollowStatusPO userFollowStatusPO : userFollowStatusPo) {
            hashMap.put(userFollowStatusPO.getTargetId(), userId);
        }
        //判断是否是互相关注
        for (MyFollowUserInfoPO myFollowUserInfoPO : myFollowUserInfoPOList) {
            if (hashMap.size() != 0) {
                Integer integer = hashMap.get(myFollowUserInfoPO.getUserId());
                if (integer != null) {
                    myFollowUserInfoPO.setFollowStatus(FollowStatus.USER_CORRELATE);
                }
            }
            // 获取头衔
            UserTitlePO userTitlePo = userTitleCacheService.getUserTitleFromCache(myFollowUserInfoPO.getTitleNameId(), myFollowUserInfoPO.getTitleLogoId());
            myFollowUserInfoPO.setUserTitlePO(userTitlePo);
        }
        return Result.success(PageUtils.restPage(myFollowUserInfoPOList));
    }

    @Override
    public Result getUserDynamicListByUserId(PageDTO pageDTO, Integer userId) {
        //判断该用户是否存在
        UserCache userCache = userCacheService.getUserMessageFromUserCacheById(userId);
        if (userCache == null) {
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
        //查询用户动态信息
        List<MyDynamicListPO> myDynamicList = dynamicMapper.getMyDynamicList(pageDTO.getEndIndexId(), userId, AnonymousStatus.ANONYMOUS);
        if (myDynamicList.size() == 0) {
            return Result.success(PageUtils.restPage(myDynamicList));
        }
        List<MyDynamicListVo> dynamicList = getDynamicList(myDynamicList, pageDTO, userId);
        return Result.success(PageUtils.restPage(myDynamicList, dynamicList));
    }

    /**
     * 获取我创建的话题列表
     *
     * @param pageDTO
     * @return
     */
    @Override
    public Result getMyCreateTopicList(PageDTO pageDTO) {
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        if (userId.equals(UserLoginStatus.UN_LOGIN)) {
            ExceptionUtils.error(WechatLoginEnum.USER_NOT_LOGIN);
        }
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
        List<Topic> topicList = topicMapper.selectListByUserIdAndDeleteStatus(userId, DeleteStatus.NO);
        ArrayList<TopicListVo> topicListVoList = new ArrayList<>(topicList.size());
        for (Topic topic : topicList) {
            TopicListVo topicListVo = new TopicListVo();
            topicListVo.setId(topic.getId());
            topicListVo.setContent(topic.getContent());
            topicListVo.setPath(topic.getPath());
            topicListVo.setTitle(topic.getTitle());
            topicListVo.setAuthenticationStatus(TopicAuthenticationStatusMap
                    .getAuthenticationStatusStr(topic.getAuthenticationStatus()));
            topicListVoList.add(topicListVo);
        }
        // 填充话题的统计信息
        topicService.fillCount(topicListVoList);
        PageUtils<TopicListVo> topicListVoPage = PageUtils.restPage(topicList, topicListVoList);
        return Result.success(topicListVoPage);
    }

    /**
     * 修改我的家乡
     *
     * @param updateHomeTownDTO 国家、省、市、县
     * @return
     */
    public Result updateMyHomeTown(UpdateHomeTownDTO updateHomeTownDTO) {
        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        // 查询用户信息
        User user = userMapper.selectOneByUserId(userId);
        if (user == null) {
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }
        if (updateHomeTownDTO.getCountry() != null) {
            user.setCountry(updateHomeTownDTO.getCountry());
        }
        if (updateHomeTownDTO.getProvince() != null) {
            user.setProvince(updateHomeTownDTO.getProvince());
        }
        if (updateHomeTownDTO.getCity() != null) {
            user.setCity(updateHomeTownDTO.getCity());
        }
        if (updateHomeTownDTO.getCounty() != null) {
            user.setCounty(updateHomeTownDTO.getCounty());
        }

        // 修改家乡信息到数据库
        Integer update = userMapper.updateBaseInfoByUser(user);
        if (update < DatabaseOperationResult.SUCCESS) {
            // 保存到数据库失败
            ExceptionUtils.error(UserEnum.USER_WX_MESSAGE_UPDATE_FAIL);
        }
        return Result.success(new UpdateHomeTownVO(user.getCountry(), user.getProvince(), user.getCity(), user.getCounty()));
    }

    /**
     * 修改当前登录用户的家乡
     *
     * @param homeTown
     * @return
     */
    @Override
    public Result updateMyHomeTown(String homeTown) {

        // 检查家乡合法性
        checkHomeTown(homeTown);

        // 获取当前用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        if (userId == UserLoginStatus.UN_LOGIN) {
            ExceptionUtils.error(WechatLoginEnum.USER_NOT_LOGIN);
        }

        // 修改数据库
        User user = userMapper.selectOneByUserId(userId);
        if (user == null) {
            ExceptionUtils.error(UserEnum.USER_INFO_NOT_EXIST);
        }
        user.setCountry(homeTown);
        Integer update = userMapper.updateBaseInfoByUser(user);
        // 检查更新到数据库是否成功
        checkUpdateSuccess(update);

        HashMap<String, String> data = new HashMap<>();
        data.put("homeTown", homeTown);
        return Result.success(data);
    }

    /**
     * 修改用户信息
     *
     * @param updateUserInfoDTO 需要修改的用户信息
     * @return
     */
    @Override
    public Result updateUserInfo(UpdateUserInfoDTO updateUserInfoDTO) {
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        userCacheService.deleteUserCache(userId);
        // 修改生日
        if (updateUserInfoDTO.getBirth() != null) {
            return updateMyBirth(updateUserInfoDTO.getBirth());
        }
        // 修改性别
        if (updateUserInfoDTO.getGender() != null) {
            return updateGender(updateUserInfoDTO.getGender());
        }
        // 修改昵称
        if (updateUserInfoDTO.getNickname() != null) {
            return updateMyNickname(updateUserInfoDTO.getNickname());
        }
        // 修改签名
        if (updateUserInfoDTO.getSignature() != null) {
            return updateMySignature(updateUserInfoDTO.getSignature());
        }
        String country = updateUserInfoDTO.getCountry();
        String province = updateUserInfoDTO.getProvince();
        String city = updateUserInfoDTO.getCity();
        String county = updateUserInfoDTO.getCounty();
        if (country != null || province != null || city != null || county != null) {
            UpdateHomeTownDTO updateHomeTownDTO = new UpdateHomeTownDTO(country, province, city, county);
            return updateMyHomeTown(updateHomeTownDTO);
        }
        // 所有参数均为空
        return Result.error(CommonEnum.REQUEST_PARAM_ERROR);
    }

    @Override
    public Result getMyInteractMessage(PageDTO pageDTO) {
        //获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);
        //获取用户消息列表
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
        //查询数据列表
        List<NewestInteractMessagePO> interactMessagePoList = messageMapper.getMyInteractMessageList(userId, pageDTO.getEndIndexId());
        if (interactMessagePoList.size() == 0) {
            return Result.success(PageUtils.restPage(interactMessagePoList));
        }
        List<InteractMessageListVO> interactMessageDeal = messageService.getInteractMessageDeal(interactMessagePoList, pageDTO.getPageSize());
        //分页处理并返回
        return Result.success(PageUtils.restPage(interactMessagePoList, interactMessageDeal));
    }

    /**
     * 获取用户热度在前20的用户信息
     *
     * @return {@link Result}
     * @author 廖振辉
     */
    @Override
    public Result getUserRankByHot() {
        Set<ZSetOperations.TypedTuple<Object>> typedTuples
                = redisCommonUtils.rangeByZSetWithScore(CacheInstruction.USER_RANK, 0, 19);
        ArrayList<UserRankVO> userRankVOList = new ArrayList<>(typedTuples.size());
        if (typedTuples.size() < 1) {
            return Result.success(userRankVOList);
        }
        // 将缓存中取到的数据转换成UserRankVO对象
        for (ZSetOperations.TypedTuple<Object> typedTuple : typedTuples) {
            double score = typedTuple.getScore() == null ? 0.0 : typedTuple.getScore();
            Integer userId = (Integer) typedTuple.getValue();
            UserPO userPO = new UserPO();
            userPO.setId(userId);
            UserRankVO userRankVO = new UserRankVO((int) score, userPO);
            userRankVOList.add(userRankVO);
        }
        // 遍历userRankVOList所有对象，从redis中取出用户的信息放进去
        for (UserRankVO userRankVO : userRankVOList) {
            // 从缓存中拿用户信息
            UserPO userPO = userRankVO.getUserPO();
            Integer userId = userPO.getId();

            UserCache userCacheObj = userCacheService.getUserMessageFromUserCacheById(userId);
            if (userCacheObj == null) {
                userCacheObj = new UserCache("用户信息获取失败", "", "");
            }
            // 将用户信息放入vo中
            UserCache userCache = userCacheObj;
            userPO.setNickname(userCache.getNickname());
            userPO.setAvatarUrl(userCache.getAvatarUrl());
            userPO.setSignature(userCache.getSignature());
        }
        return Result.success(userRankVOList);
    }

    /**
     * 获取我在用户活跃度总榜的排名
     *
     * @return {@link Result}
     * @author 廖振辉
     */
    @Override
    public Result getMyHotRank() {
        // 获取用户id
        Integer userId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);

        UserRankVO userRankVO = new UserRankVO();
        // 获取用户信息
        Object userInfoFromCache = redisCommonUtils.hget(CacheInstruction.USER_CACHE, userId);
        if (userInfoFromCache != null) {
            UserCache userCache = (UserCache) userInfoFromCache;
            UserPO userPO = new UserPO();
            userPO.setId(userCache.getId());
            userPO.setNickname(userCache.getNickname());
            userPO.setSignature(userCache.getSignature());
            userPO.setAvatarUrl(userCache.getAvatarUrl());
            userRankVO.setUserPO(userPO);
        } else {
            // 缓存中无用户信息
            UserPO userPO = getUserPartInfoById(userId);
            userRankVO.setUserPO(userPO);
        }
        // 获取用户在总榜中的排名
        Long rank = redisCommonUtils.zrevrank(CacheInstruction.USER_RANK, userId);
        if (!Long.valueOf(-1L).equals(rank)) {
            userRankVO.setRank(rank.intValue() + 1);
        }
        return Result.success(userRankVO);
    }

    /**
     * 获取所有用户列表
     *
     * @param pageDTO 分页对象
     * @return {@link Result}
     * @author 廖振辉
     */
    @Override
    public Result getAllUserList(PageDTO pageDTO) {
        PageHelper.startPage(pageDTO.getPageNum(), pageDTO.getPageSize());
        List<UserPO> userPOList = userMapper.selectListOrderByCreateTimeDEsc(pageDTO.getEndIndexId());
        List<TotalUserVO> totalUserVOList = new ArrayList<>(userPOList.size());
        for (UserPO userPO : userPOList) {
            TotalUserVO totalUserVO = new TotalUserVO(userPO, userPO.getId());
            totalUserVOList.add(totalUserVO);
        }
        PageUtils<TotalUserVO> totalUserVOPage = PageUtils.restPage(userPOList, totalUserVOList);
        return Result.success(totalUserVOPage);
    }

    /**
     * 根据用户名搜索用户
     *
     * @param searchUserDTO
     * @return {@link Result}
     * @author 廖振辉
     */
    @Override
    public Result searchUser(SearchUserDTO searchUserDTO) {
        String nickname = searchUserDTO.getNickname();
        if (StringUtils.isEmpty(nickname)) {
            nickname = null;
        }
        PageHelper.startPage(searchUserDTO.getPageNum(), searchUserDTO.getPageSize());
        List<UserPO> userPOList = userMapper.selectListLikeNickname(nickname);
        List<TotalUserVO> totalUserVOList = new ArrayList<>(userPOList.size());
        for (UserPO userPO : userPOList) {
            TotalUserVO totalUserVO = new TotalUserVO(userPO, userPO.getId());
            totalUserVOList.add(totalUserVO);
        }
        PageUtils<TotalUserVO> totalUserVOPage = PageUtils.restPage(userPOList, totalUserVOList);
        return Result.success(totalUserVOPage);
    }

    /**
     * 获取用户总数
     *
     * @return {@link Result}
     * @author 廖振辉
     */
    @Override
    public Result getTotalUserCount() {
        Integer total = userMapper.countTotal();
        HashMap<String, Integer> data = new HashMap<>();
        data.put("total", total);
        return Result.success(data);
    }

    /**
     * 检查家乡合法性
     *
     * @param homeTown
     */
    private void checkHomeTown(String homeTown) {
        // 判断参数是否为空
        if (StringUtils.isEmpty(homeTown)) {
            ExceptionUtils.error(UserEnum.HOMETOWN_IS_NULL);
        }
    }

    /**
     * 封装动态结果处理
     *
     * @param list
     * @param pageDTO
     * @return
     */
    public List<MyDynamicListVo> getDynamicList(List<MyDynamicListPO> list, PageDTO pageDTO, int userId) {

        //获取本人的id
        Integer meId = JwtUtils.getMemberIdByJwtToken(httpServletRequest);


        //合并结果到Vo中
        List<MyDynamicListVo> totalDynamicListVoList = new ArrayList<>();
        for (MyDynamicListPO MyDynamicListPo : list) {
            MyDynamicListVo totalDynamicListVo = new MyDynamicListVo();
            //加入动态id
            int dynamicId = MyDynamicListPo.getId();
            totalDynamicListVo.setId(dynamicId);
            //加入动态内容
            totalDynamicListVo.setContent(MyDynamicListPo.getContent());
            totalDynamicListVo.setStatus(MyDynamicListPo.getStatus());
            totalDynamicListVo.setCreateTime(MyDynamicListPo.getCreateTime());
            totalDynamicListVo.setDynamicPlace(MyDynamicListPo.getDynamicPlace());

            //获取用户信息 考虑用户不存在的情况
            //加入匿名用户信息
            if (Integer.valueOf(AnonymousStatus.ANONYMOUS).equals(MyDynamicListPo.getStatus())) {
                //从缓存中获取匿名信息
                AnonymousUser anonymousUser = anonyUserService.getAnonymousUserById(MyDynamicListPo.getAnonymousUserId());
                totalDynamicListVo.setAnonymousName(anonymousUser.getAnonymousName());
                totalDynamicListVo.setAnonymousAvatarUrl(anonymousUser.getAnonymousAvatarUrl());
                totalDynamicListVo.setUserId(null);
            } else {
                //否则加入用户信息，从缓存中获取信息并加入
                UserCache userCache = userCacheService.getUserMessageFromUserCacheById(MyDynamicListPo.getUserId());
                totalDynamicListVo.setNickname(userCache.getNickname());
                totalDynamicListVo.setAvatarUrl(userCache.getAvatarUrl());
                totalDynamicListVo.setUserId(userCache.getId());

                // 获取头衔限制了速度点瓶颈
                // 获取头衔
                UserTitlePO userTitlePo = userTitleCacheService.getUserTitleFromCache(userCache.getTitleNameId(), userCache.getTitleLogoId());
                totalDynamicListVo.setUserTitlePO(userTitlePo);
            }

            //加入动态图片
            List<DynamicPicturePO> dynamicPictures = pictureCacheService.getDynamicPicturePoFromCache(dynamicId);
            totalDynamicListVo.setDynamicPicturePo(dynamicPictures);

            //加入动态点赞数目 、 评论数目 、转发数目
            DynamicStatistic dynamicStatistic = dynamicCacheService.getDynamicStatistic(dynamicId);
            totalDynamicListVo.setDynamicLoveCount(dynamicStatistic.getLoveCount());
            totalDynamicListVo.setDynamicCommentCount(dynamicStatistic.getCommentCount());
            totalDynamicListVo.setDynamicForwardCount(dynamicStatistic.getForwardCount());


            //加入用户对动态的点赞信息
            boolean flag = userCacheService.getUserDynamicLoveStatusFromCache(meId, dynamicId);
            if (flag) {
                totalDynamicListVo.setLoveStatus(LoveStatus.LOVE);
            } else {
                totalDynamicListVo.setLoveStatus(LoveStatus.UN_LOVE);
            }

            //存储用户的关注状态
            boolean flag2 = userCacheService.getUserFollowStatus(meId, MyDynamicListPo.getUserId());
            if (flag2) {
                totalDynamicListVo.setFollowStatus(FollowStatus.FOLLOW);
            } else {
                totalDynamicListVo.setFollowStatus(FollowStatus.UN_FOLLOW);
            }
            //添加话题信息, 考虑没有对应话题的情况
            if ( MyDynamicListPo.getTopicId()!= null && MyDynamicListPo.getTopicId() != 0){
                Topic topic = topicCacheService.getTopicMessageFromCache(MyDynamicListPo.getTopicId());
                if (topic != null){
                    totalDynamicListVo.setTopicId(topic.getId());
                    totalDynamicListVo.setTitle(topic.getTitle());
                }
            }
            //添加到集合汇总
            totalDynamicListVoList.add(totalDynamicListVo);
        }

        return totalDynamicListVoList;
    }

        /**
         * 从点赞库中，统计指定用户的获赞数
         *
         * @param userId
         * @return
         */
        private Integer getBeLovedCountByUserId (Integer userId){
            Integer countSum = 0;
            // 动态点赞
            Integer dynamicLoveCount = dynamicLoveMapper.countLoveByUserId(userId);
            countSum += dynamicLoveCount;
            // 动态评论点赞数
            Integer dynamicCommentCount = dynamicCommentLoveMapper.countLoveByUerId(userId);
            countSum += dynamicCommentCount;
            // 动态评论回复点赞数
            Integer dynamicCommentReplyCount = dynamicCommentReplyLoveMapper.countLoveByUerId(userId);
            countSum += dynamicCommentReplyCount;
            // 问答评论点赞数
            Integer questionCommentCount = questionCommentLoveMapper.countLoveByUerId(userId);
            countSum += questionCommentCount;
            // 问答评论回复点赞数
            Integer questionCommentReplyCount = questionCommentReplyLoveMapper.countLoveByUerId(userId);
            countSum += questionCommentReplyCount;
            return countSum;
        }

        /**
         * 检查输入的字符串日期是否格式正确，若正确则返回一个日期对象
         *
         * @param birthStr 字符串格式的生日
         * @return
         */
        private Date checkBirth (String birthStr){
            // 若没有携带该请求参数
            if (StringUtils.isEmpty(birthStr)) {
                ExceptionUtils.error(CommonEnum.REQUEST_PARAM_ERROR);
            }
            // 判断
            Date birth = null;
            try {
                birth = new SimpleDateFormat("yyyy-MM-dd").parse(birthStr);
            } catch (ParseException e) {
                ExceptionUtils.error(UserEnum.BIRTH_FORMAT_ERROR);
            }
            // 判断用户输入的日期是否不合理，如2022-22-22
            String[] split = birthStr.split("-");// split数组元素为[年，月，日]
            for (int i = 0; i < split.length; i++) {
                int num = Integer.parseInt(split[i]);
                if (i == 0 && num > Calendar.getInstance().get(Calendar.YEAR)) {
                    // 检测年是否大于今年
                    ExceptionUtils.error(UserEnum.BIRTH_TOO_LATE);
                } else if (i == 1 && (num < 1 || num > 12)) {
                    ExceptionUtils.error(UserEnum.BIRTH_MONTH_NOT_IN_RANGE);
                } else if (i == 2 && (num < 1 || num > 31)) {
                    ExceptionUtils.error(UserEnum.BIRTH_DAY_NOT_IN_RANGE);
                }
            }
            return birth;
        }
    }
